package adrian.sunlight.jsp.servlets;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.dyuproject.oauth.Constants;
import com.dyuproject.oauth.Consumer;
import com.dyuproject.oauth.ConsumerContext;
import com.dyuproject.oauth.Endpoint;
import com.dyuproject.oauth.HttpAuthTransport;
import com.dyuproject.oauth.Token;
import com.dyuproject.oauth.TokenExchange;
import com.dyuproject.oauth.Transport;
import com.dyuproject.util.http.HttpConnector;
import com.dyuproject.util.http.UrlEncodedParameterMap;
import com.dyuproject.util.http.HttpConnector.Parameter;
import com.dyuproject.util.http.HttpConnector.Response;

/**
 * Servlet implementation class GoogleOauthServlet
 */
public class GoogleOAuthServlet extends HttpServlet{

    /**
	 * 
	 */
	private static final long serialVersionUID = -267343580977828124L;

	static String GOOGLE_SERVICE_URL= "http://www.google.com/m8/feeds/contacts/default/full";
    static String GOOGLE_API_SCOPE  = "http://www.google.com/m8/feeds/";
	static String OAUTH_CALLBACK_URL= "";
	static String DEFAULT_REDIRECT  = "/index.jsp";
    
    Consumer _consumer = Consumer.getInstance();
    Endpoint _googleEndpoint = _consumer.getEndpoint("www.google.com");
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{
    	
    	 this.processRequest(request, response);
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{
    	
        this.processRequest(request, response);
    }
    
    public void processRequest(HttpServletRequest request, HttpServletResponse response) 
    throws IOException, ServletException{
    	
    	//------Initialize Google API Params----------//
    	
    	 OAUTH_CALLBACK_URL = request.getRequestURL().toString();
    	
    	if(request.getParameter("default_redirect") != null){
    		DEFAULT_REDIRECT = request.getParameter("default_redirect");
     	}
    	 
    	if(request.getParameter("scope") != null){
    		GOOGLE_API_SCOPE = request.getParameter("scope");
    	}
    	
    	if(request.getParameter("service_url") != null){
    		GOOGLE_SERVICE_URL = request.getParameter("service_url");
    	}
    	
    	if(request.getParameter("oauth_callback") != null){
    		OAUTH_CALLBACK_URL = request.getParameter("oauth_callback");
    	}
    	
    	Token token = _consumer.getToken(_googleEndpoint.getConsumerKey(), request);
        switch(token.getState()){
        
            case Token.UNITIALIZED:
                UrlEncodedParameterMap params = new UrlEncodedParameterMap()
                    .add("scope", GOOGLE_API_SCOPE)
                    .add(Constants.OAUTH_CALLBACK, OAUTH_CALLBACK_URL);
                    
                Response r = _consumer.fetchToken(_googleEndpoint, params, TokenExchange.REQUEST_TOKEN, 
                        token);
                if(r.getStatus()==200 && token.getState()==Token.UNAUTHORIZED)
                {
                    // unauthorized request token
                    _consumer.saveToken(token, request, response);
                    StringBuilder urlBuffer = Transport.buildAuthUrl(
                            _googleEndpoint.getAuthorizationUrl(), token);
                    Transport.appendToUrl("hd", "default", urlBuffer);
                    response.sendRedirect(urlBuffer.toString());
                }
                break;
                
            case Token.UNAUTHORIZED:
                if(token.authorize(request.getParameter(Constants.OAUTH_TOKEN), 
                        request.getParameter(Constants.OAUTH_VERIFIER)))
                {
                    if(fetchAccessToken(token, request, response))
                    	queryGoogleService(token, request, response);
                    else
                        _consumer.saveToken(token, request, response);
                }
                break;
                
            case Token.AUTHORIZED:
                if(fetchAccessToken(token, request, response))
                	queryGoogleService(token, request, response);
                break;
                
            case Token.ACCESS_TOKEN:
            	queryGoogleService(token, request, response);
                break;
                
            default:
                response.sendRedirect(request.getContextPath() + "/index.jsp");
        }
    }
    
    public boolean fetchAccessToken(Token token, HttpServletRequest request, 
            HttpServletResponse response) throws IOException{
    	
        // authorized request token
        UrlEncodedParameterMap params = new UrlEncodedParameterMap();
        
        Response r = _consumer.fetchToken(_googleEndpoint, params, TokenExchange.ACCESS_TOKEN, token);
        if(r.getStatus()==200 && token.getState()==Token.ACCESS_TOKEN)
        {
            // access token
            _consumer.saveToken(token, request, response);
            return true;
        }
        return false;
    }
    
    public static Response serviceGET(String serviceUrl, ConsumerContext context, Endpoint ep, Token token) 
            throws IOException{
    	
        HttpConnector connector = context.getHttpConnector();
        
        UrlEncodedParameterMap params = new UrlEncodedParameterMap(serviceUrl);
        
        context.getNonceAndTimestamp().put(params, token.getCk());
        
        Parameter authorization = new Parameter("Authorization", 
                HttpAuthTransport.getAuthHeaderValue(params, ep, token, 
                context.getNonceAndTimestamp(),  ep.getSignature()));
        
        return connector.doGET(params.getUrl(), authorization);
        
    }
    
    //TODO 
    public static Response servicePOST(String serviceUrl, ConsumerContext context, Endpoint ep, 
    		Token token, HashMap<?, ?> RequestParameters)throws IOException{
    	
        HttpConnector connector = context.getHttpConnector();
        
        UrlEncodedParameterMap params = new UrlEncodedParameterMap(serviceUrl);
        
        context.getNonceAndTimestamp().put(params, token.getCk());
        
        Parameter authorization = new Parameter("Authorization", 
                HttpAuthTransport.getAuthHeaderValue(params, ep, token, 
                context.getNonceAndTimestamp(),  ep.getSignature()));

        Response resp = connector.doPOST(serviceUrl, authorization, params, "utf-8");
        
        System.out.println(resp.toString());
        //return connector.doPOST(serviceUrl, authorization, params, "utf-8");
        return null;
    }
    
    protected void queryGoogleService(Token token, HttpServletRequest request, 
            HttpServletResponse response) throws IOException{
    	
        Response r = serviceGET(GOOGLE_SERVICE_URL, _consumer.getConsumerContext(), _googleEndpoint, token);
        
        BufferedReader br = new BufferedReader(new InputStreamReader(r.getInputStream(), "UTF-8"));
        response.setContentType("text/xml");
        
        //----afiseaza raspunsul ------------//
        PrintWriter pw = response.getWriter();
        for(String line=null; (line=br.readLine())!=null;){
        	pw.append(line);
        }   
    }
}
